今日内容	
	1. 多表查询//特别重要

	2. 事务//重要

	3. DCL//了解
			
	* 查询语法：
	select
		列名列表
	from
		表名列表
	where....
	* 准备sql
		# 创建部门表
		CREATE TABLE dept(
			id INT PRIMARY KEY AUTO_INCREMENT,
			NAME VARCHAR(20)
		);
		INSERT INTO dept (NAME) VALUES ('开发部'),('市场部'),('财务部');
		# 创建员工表
		CREATE TABLE emp (
			id INT PRIMARY KEY AUTO_INCREMENT,
			NAME VARCHAR(10),
			gender CHAR(1), -- 性别
			salary DOUBLE, -- 工资
			join_date DATE, -- 入职日期
			dept_id INT,
			FOREIGN KEY (dept_id) REFERENCES dept(id) -- 外键，关联部门表(部门表的主键)
		);
		INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('孙悟空','男',7200,'2013-02-24',1);
		INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('猪八戒','男',3600,'2010-12-02',2);
		INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('唐僧','男',9000,'2008-08-08',2);
		INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('白骨精','女',5000,'2015-10-07',3);
		INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('蜘蛛精','女',4500,'2011-03-14',1);
	* 笛卡尔积：
		* 有两个集合A,B .取这两个集合的所有组成情况。
		* 要完成多表查询，需要消除无用的数据
		
		例如：
			{a,b,c}    {1,2}
			{a1,a2,b1,b2,c1,c2}
			
	问题：
		1.为什么要用笛卡尔积？
			就是为了把两张表中的数据进行组合
		2.弊端
			产生了大量的冗余（无用）数据
		3.怎么解决
			去除笛卡尔积（通过where 主外键关系）
			
		4.总结：只要使用连接查询的时候，必须要去除笛卡尔积
		
		
	* 多表查询的分类：
		1. 内连接查询：
			1. 隐式内连接：使用where条件消除无用数据
				* 例子：
				-- 查询所有员工信息和对应的部门信息

				SELECT * FROM emp,dept WHERE emp.`dept_id` = dept.`id`;
				
				-- 查询员工表的名称，性别。部门表的名称
				SELECT emp.name,emp.gender,dept.name FROM emp,dept WHERE emp.`dept_id` = dept.`id`;
				
				SELECT 
					t1.name, -- 员工表的姓名
					t1.gender,-- 员工表的性别
					t2.name -- 部门表的名称
				FROM
					emp t1,
					dept t2
				WHERE 
					t1.`dept_id` = t2.`id`;	
//------------------------------------------------------------------------------------------------------------------------

	多表查询的分类：
		1. 内连接查询：
			1. 隐式内连接：使用where条件消除无用数据  //推荐使用
			//内连接的作用：消除无用数据
				* 例子：
				-- 查询所有员工信息和对应的部门信息

				SELECT * FROM emp,dept WHERE emp.`dept_id` = dept.`id`;
				
				-- 查询员工表的名称，性别。部门表的名称
				SELECT emp.name,emp.gender,dept.name FROM emp,dept WHERE emp.`dept_id` = dept.`id`;
				
				SELECT 
					t1.name, -- 员工表的姓名
					t1.gender,-- 员工表的性别
					t2.name -- 部门表的名称
				FROM
					emp t1,
					dept t2
				WHERE 
					t1.`dept_id` = t2.`id`;				
			//select 字段列表 from 	表名1 , 表名2 on 条件
			2. 显式内连接：  //至少能看懂
			* 语法： select 字段列表 from 表名1 [inner] join 表名2 on 条件
			* 例如：
				* SELECT * FROM emp INNER JOIN dept ON emp.`dept_id` = dept.`id`;	
				* SELECT * FROM emp JOIN dept ON emp.`dept_id` = dept.`id`;	

			3. 内连接查询：
				1. 从哪些表中查询数据
				2. 条件是什么
				3. 查询哪些字段		
						
		2. 外链接查询：
			//外连接是为了解决什么问题的？
				//解决交集以外的数据问题
			1. 左外连接：
				* 语法：select 字段列表 from 表1 left [outer] join 表2 on 条件；
				* 查询的是左表所有数据以及其交集部分。
				* 例子：
					-- 查询所有员工信息，如果员工有部门，则查询部门名称，没有部门，则不显示部门名称
					SELECT 	t1.*,t2.`name` FROM emp t1 LEFT JOIN dept t2 ON t1.`dept_id` = t2.`id`;
			2. 右外连接：
				* 语法：select 字段列表 from 表1 right [outer] join 表2 on 条件；
				* 查询的是右表所有数据以及其交集部分。
				* 例子：
					SELECT 	* FROM dept t2 RIGHT JOIN emp t1 ON t1.`dept_id` = t2.`id`;			
			//内连接、左外连接、右外连接的区别					
				内连接：A表和B表的交集
				左外连接：A表的所有数据+交集
				右外连接：交集+右表的所有数据
			//什么叫左  什么叫右？
				SELECT 	t1.*,t2.`name` FROM emp t1 LEFT JOIN dept t2 ON t1.`dept_id` = t2.`id`;
				在左边的就是左表，在右边的就是右表	
					
		3. 子查询：
			* 概念：查询中嵌套查询，称嵌套查询为子查询。
				-- 查询工资最高的员工信息
				-- 1 查询最高的工资是多少 9000
				SELECT MAX(salary) FROM emp;
				
				-- 2 查询员工信息，并且工资等于9000的
				SELECT * FROM emp WHERE emp.`salary` = 9000;
				
				-- 一条sql就完成这个操作。子查询
				SELECT * FROM emp WHERE emp.`salary` = (SELECT MAX(salary) FROM emp);			
					
			* 子查询不同情况
			1. 子查询的结果是单行单列的：
				* 子查询可以作为条件，使用运算符去判断。 运算符： > >= < <= =
				* 
				-- 查询员工工资小于平均工资的人
				SELECT * FROM emp WHERE emp.salary < (SELECT AVG(salary) FROM emp);
		//聚合函数不能直接作为查询条件,如:where 表名1.列名n=COUNT(表名2.列名m),聚合函数只能通过子查询作为查询条件被使用,要么就作为查询字段被使用
		//having后面可以直接跟聚合函数作为查询条件,如:having MAX(t1.ID) >10
			2. 子查询的结果是多行单列的：
				* 子查询可以作为条件，使用运算符in来判断
				-- 查询'财务部'和'市场部'所有的员工信息
				SELECT id FROM dept WHERE NAME = '财务部' OR NAME = '市场部';
				SELECT * FROM emp WHERE dept_id = 3 OR dept_id = 2;
				-- 子查询
				SELECT * FROM emp WHERE dept_id IN (SELECT id FROM dept WHERE NAME = '财务部' OR NAME = '市场部');

			3. 子查询的结果是多行多列的：
				* 子查询可以作为一张虚拟表参与查询
				-- 查询员工入职日期是2011-11-11日之后的员工信息和部门信息
				-- 子查询
				SELECT * FROM dept t1 ,(SELECT * FROM emp WHERE emp.`join_date` > '2011-11-11') t2
				WHERE t1.id = t2.dept_id;
				
				-- 普通内连接
				SELECT * FROM emp t1,dept t2 WHERE t1.`dept_id` = t2.`id` AND t1.`join_date` >  '2011-11-11'
				//子查询如果是多行多列的,那么通常作为虚拟表来使用,如果虚拟表中的列名是是带有聚合函数的,当进行多表查询时,且查询条件有虚拟表中的
				//聚合函数部分,如果直接用t1.MAX(ID)会报错,应该在虚拟表中将带聚合函数的列名改成其他的名字,这样才不会报错
				//不建议在select关键字后使用子查询!如果这样会影响sql的执行效率	
			多表查询的分析步骤：
				（1）分析要查询的字段都在哪些表中------------相当找到了我们需要使用哪几张表
				（2）表与表之间的关联关系
				（3）把要查询的字段从各个表中捞出来
				
				
				
			4.  联合查询:
				union联合: 要求是多个结果集的列名和列数必须一致//这样查询的结果就是两个sql语句分别执行完成后,然后又拼接在一起的效果
				//如SELECT * FROM 	t_order WHERE  setmeal_id = 5结果为两行执行结果,SELECT * FROM 	t_order WHERE  setmeal_id = 7结果为三行执行结果
				//那么最终下面这段sql就是这两条sql语句分别执行的结果的并集,就是五条执行结果
				SELECT * FROM 	t_order WHERE  setmeal_id = 5
				union
				SELECT * FROM 	t_order WHERE  setmeal_id = 7
									
事务	
	1. 事务的基本介绍
		1. 概念：
			*  如果一个包含多个步骤的业务操作，被事务管理，那么这些操作要么同时成功，要么同时失败。
			//什么叫事务(☆☆☆☆☆)
				//事务也叫业务。  一个包含多个步骤（sql语句，不包括查询）的业务操作（增删改）  转账
			//事务的特点？
					"同生共死"
				//同时成功，要么同时失败   同时成功的时候，提交进数据库； 同时失败则回滚到开启事务的时候。
			
		2. 操作：//事务的操作步骤
			1. 开启事务： start transaction;
				//执行多条sql 语句
			2. 回滚：rollback;
			3. 提交：commit;
		3. 例子：
			CREATE TABLE account (
				id INT PRIMARY KEY AUTO_INCREMENT,
				NAME VARCHAR(10),
				balance DOUBLE
			);
			-- 添加数据
			INSERT INTO account (NAME, balance) VALUES ('zhangsan', 1000), ('lisi', 1000);
			
		SELECT * FROM account;
			UPDATE account SET balance = 1000;
			-- 张三给李四转账 500 元
			
			-- 0. 开启事务
			START TRANSACTION;
			//当系统读取到START TRANSACTION;开启事务的语句时,接下来执行的每条语句之前,系统默认将不再开启事务,开启事务相当于一个标识
			//当读取到commit或rollback时,将提交START TRANSACTION到commit/rollback之间代码体的执行结果
			-- 1. 张三账户 -500
			
			UPDATE account SET balance = balance - 500 WHERE NAME = 'zhangsan';
			-- 2. 李四账户 +500
			-- 出错了...
			UPDATE account SET balance = balance + 500 WHERE NAME = 'lisi';
			
			-- 发现执行没有问题，提交事务
			COMMIT;
			//手动提交,如果前面的执行结果没问题,就提交事务
			-- 发现出问题了，回滚事务
			ROLLBACK;
			//手动执行,如果前面的执行结果部分语句出现了问题,就回滚事务
		4. MySQL数据库中事务默认自动提交
			
			* 事务提交的两种方式：
				* 自动提交：
					* mysql就是自动提交的
					* 一条DML(增删改查)语句会自动提交一次事务。
					//一条DML增删改查语句会自动开启事务,当执行完毕后,会自动提交一次事务
					//同时执行多条语句，每条SQL语句执行完成后都会被当成单独的事务自动提交
				* 手动提交：
					* Oracle 数据库默认是手动提交事务
					* 需要先开启事务，再提交
			* 修改事务的默认提交方式：
				* 查看事务的默认提交方式：SELECT @@autocommit; -- 1 代表自动提交  0 代表手动提交
				* 修改默认提交方式： set @@autocommit = 0;	
				//如果没有START TRANSACTION;开启事务的标志,那么就默认在每条语句执行之前开启事务,只有读到了COMMIT;才会提交事务,如果读到了
				//ROLLBACK;就会回滚到每条语句开始事务的时候
				//例如:set @@autocommit = 0;
					语句一:UPDATE account SET balance=20 WHERE id=1;(默认在执行这条语句之前开始了事务)
					语句二:UPDATE account SET balance=50 WHERE id =2;(默认在执行这条语句之前开始了事务)
					COMMIT;/ROLLBACK;(当读到commit时,语句一和语句二就会提交当前事物,使执行结果保存,当读到rollback时,语句一和语句二就会都回滚到开始事务之前).

					
			//需要大家掌握两点
				(1)	我们以前对数据库进行增删改的时候，mysql是帮我们自动开启了一个事务，执行完后又默认帮我们提交了事务。
						update  dept  set  name  =  "开发部"；
					* 开启事务
					*执行update  dept  set  name  =  "开发部"；
					*如果成功-----提交事务（commit）
					*如果失败-----提交回滚操作（rollback）
				（2）如果我们手动开启了一个事务，那么这个时候mysql就不会再帮我们自动开启事务了，在最后需要我们自己手动提交。	
					
	2. 事务的四大特征：//常见面试题和笔试单选题
		1. 原子性：是不可分割的最小操作单位，要么同时成功，要么同时失败。
		2. 持久性：当事务提交或回滚后，数据库会持久化的保存数据。
		3. 隔离性：多个事务之间。相互独立。
		4. 一致性：事务操作前后，数据总量不变。				
			"原持一隔"		
	3. 事务的隔离级别（了解）
		* 概念：多个事务之间隔离的，相互独立的。但是如果多个事务操作同一批数据，则会引发一些问题，设置不同的隔离级别就可以解决这些问题。
		* 存在问题：
			1. 脏读：一个事务，读取到另一个事务中没有提交的数据
			2. 不可重复读(虚读)：在同一个事务中，两次读取到的数据不一样。
			3. 幻读：一个事务操作(DML)数据表中所有记录，另一个事务添加了一条数据，则第一个事务查询不到自己的修改。
		* 隔离级别：
			1. read uncommitted：读未提交
				* 产生的问题：脏读、虚读、幻读
			2. read committed：读已提交 （Oracle）
				* 产生的问题：虚读、幻读
			3. repeatable read：不可虚读 （MySQL默认）
				* 产生的问题：幻读
				//A窗口开启了事务,B窗口必须要手动开启事务,否则还是会产生虚读效果
			4. serializable：串行化
				* 可以解决所有的问题

			* 注意：隔离级别从小到大安全性越来越高，但是效率越来越低
			* 数据库查询隔离级别：
				* select @@tx_isolation;
			* 数据库设置隔离级别：
				* set global transaction isolation level  级别字符串;	
		//在以后的开发中，我们不需要去修改mysql的默认隔离级别，直接使用默认的就行。

DCL：
	* SQL分类：
	1. DDL：操作数据库和表
	2. DML：增删改表中数据
	3. DQL：查询表中数据
	4. DCL：管理用户，授权

* DBA：数据库管理员

* DCL：管理用户，授权
	1. 管理用户
		1. 添加用户：
			* 语法：CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码';
			//添加一个新用户,给定新用户的用户名,主机名(IP地址也可以),密码,让其在对应的主机登录数据库服务器
			//例如数据库服务器是1.1.1.1 ,那么在数据库服务器上添加新用户create user 'liuxudong'@'1.1.1.2' IDENTIFIED BY '123456';
			//那么在1.1.1.2上远程登录时要输入服务器的IP,以及用户名:'liuxudong',密码:'123456'
		2. 删除用户：
			* 语法：DROP USER '用户名'@'主机名';
		3. 修改用户密码：
			//方式一
			UPDATE USER SET PASSWORD = PASSWORD('新密码') WHERE USER = '用户名';
			UPDATE USER SET PASSWORD = PASSWORD('abc') WHERE USER = 'lisi';
			
			//方式二
			SET PASSWORD FOR '用户名'@'主机名' = PASSWORD('新密码');
			SET PASSWORD FOR 'root'@'localhost' = PASSWORD('123');

			* mysql中忘记了root用户的密码？
				1. cmd -- > net stop mysql 停止mysql服务
					* 需要管理员运行该cmd

				2. 使用无验证方式启动mysql服务： mysqld --skip-grant-tables
				3. 打开新的cmd窗口,直接输入mysql命令，敲回车。就可以登录成功
				4. use mysql;
				5. update user set password = password('你的新密码') where user = 'root';
				6. 关闭两个窗口
				7. 打开任务管理器，手动结束mysqld.exe 的进程
				8. 启动mysql服务
				9. 使用新密码登录。
		4. 查询用户：
			-- 1. 切换到mysql数据库
			USE myql;
			-- 2. 查询user表
			SELECT * FROM USER;
			
			* 通配符： % 表示可以在任意主机使用用户登录数据库

	2. 权限管理：
		1. 查询权限：
			-- 查询权限
			SHOW GRANTS FOR '用户名'@'主机名';
			SHOW GRANTS FOR 'lisi'@'%';

		2. 授予权限：
			-- 授予权限
			grant 权限列表 on 数据库名.表名 to '用户名'@'主机名';
			-- 给张三用户授予所有权限，在任意数据库任意表上
			
			GRANT ALL ON *.* TO 'zhangsan'@'localhost';
			//这里的主机名必须和user表中的用户名和主机名对应,user表中zhangsan对应的主机名如果是localhost,那么撤销权限必须填localhost
		3. 撤销权限：
			-- 撤销权限：
			revoke 权限列表 on 数据库名.表名 from '用户名'@'主机名';
			REVOKE UPDATE ON db3.`account` FROM 'lisi'@'%';
			//这里的主机名必须和user表中的用户名和主机名对应,user表中lisi对应的主机名如果是%,那么撤销权限必须填%,不可以因为lisi可以在
			//任意主机登录,只撤销其在其中某台主机的权限
			
			
			
			
			事务的四大特性ACID

			1、原子性（Atomicity）

			　　原子性是指事务包含的所有操作要么全部成功，要么全部失败回滚，因此事务的操作如果成功就必须要完全应用到数据库，如果操作失败则不能对数据库有任何影响。

			2、一致性（Consistency）

			　　一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态，也就是说一个事务执行之前和执行之后都必须处于一致性状态。

			　　拿转账来说，假设用户A和用户B两者的钱加起来一共是5000，那么不管A和B之间如何转账，转几次账，事务结束后两个用户的钱相加起来应该还得是5000，这就是事务的一致性。

			3、隔离性（Isolation）

			　　隔离性是当多个用户并发访问数据库时，比如操作同一张表时，数据库为每一个用户开启的事务，不能被其他事务的操作所干扰，多个并发事务之间要相互隔离。

			　　即要达到这么一种效果：对于任意两个并发的事务T1和T2，在事务T1看来，T2要么在T1开始之前就已经结束，要么在T1结束之后才开始，这样每个事务都感觉不到有其他事务在并发地执行。

			4、持久性（Durability）

			　　持久性是指一个事务一旦被提交了，那么对数据库中的数据的改变就是永久性的，即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

			　　例如我们在使用JDBC操作数据库时，在提交事务方法后，提示用户事务操作完成，当我们程序执行完成直到看到提示后，就可以认定事务以及正确提交，

			  隔离级别                 	脏读  	不可重复读	幻读  
			  读未提交  Read UnCommited	√   	√    	√   
			  读已提交  Read Commited  	×   	√    	√   
			  可重复读  Repeatable Read	×   	×    	√   
			  序列化      Serializable	×   	×    	×   



-------------------------------------------------------------------------------









		
					
					